package org.zoomdev.zoom.common.caster;

import org.zoomdev.zoom.common.io.Io;
import org.zoomdev.zoom.common.json.JSON;
import org.zoomdev.zoom.common.utils.Classes;

import java.io.Reader;
import java.lang.reflect.Type;
import java.sql.Blob;
import java.sql.Clob;
import java.sql.SQLException;

class ClobAndBlob {
    static class Blob2ByteArray implements ValueCaster {
        @Override
        public Object to(Object src) {
            Blob blob = (Blob) src;
            try {
                return blob.getBytes(1L, (int) blob.length());
            } catch (SQLException e) {
                throw new CasterException(e);
            }
        }

    }

    static class Blob2String implements ValueCaster {
        @Override
        public Object to(Object src) {
            Blob blob = (Blob) src;
            try {
                return Base64.encodeToString(blob.getBytes(1, (int) blob.length()), false);
            } catch (SQLException e) {
                throw new CasterException(e);
            }
        }

    }

    public static class Clob2AnyProvider implements CasterProvider {
        @Override
        public ValueCaster getCaster(Class<?> srcType, Type toType) {
            if (Clob.class.isAssignableFrom(srcType)) {
                if (toType instanceof Class) {
                    if (Classes.isSimple((Class<?>) toType)) {
                        return null;
                    }
                }
                return new Clob2Other(toType);
            }
            return null;
        }
    }

    static class Clob2String implements ValueCaster {
        @Override
        public Object to(Object src) {
            Clob clob = (Clob) src;
            try {
                return clob.getSubString(1, (int) clob.length());
            } catch (SQLException e) {
                throw new CasterException(e);
            }
        }

    }

    /**
     * convert clob to JavaType
     */
    static class Clob2Other implements ValueCaster {

        Type javaType;

        Clob2Other(Type javaType) {
            this.javaType = javaType;
        }

        @Override
        public Object to(Object src) {
            Reader reader = null;
            try {
                Clob clob = (Clob) src;
                reader = clob.getCharacterStream();
                return JSON.parse(reader, javaType);
            } catch (Exception e) {
                throw new CasterException(e);
            } finally {
                Io.close(reader);
            }

        }
    }
}
